package com.itlaobing.exam.controller;

import com.itlaobing.exam.entity.User;
import com.itlaobing.exam.service.UserService;
import com.itlaobing.exam.support.UserRole;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Objects;
import java.util.logging.Logger;

@WebServlet( "/user/*" )
public class UserServlet extends HttpServlet {

    private static final char SLASH = '/' ;

    private static final String LOGIN_USER = "user" ;

    private final Logger logger = Logger.getLogger( this.getClass().getName() );

    @Override
    protected void service( HttpServletRequest request , HttpServletResponse response )
            throws ServletException, IOException {

        request.setCharacterEncoding( "UTF-8" );
        response.setCharacterEncoding( "UTF-8" );

        // 获取本次用户的请求路径
        String uri = request.getRequestURI() ;
        logger.info( uri );

        int first = uri.indexOf( SLASH ) ; // 查找第一个 / 的位置
        int last = uri.lastIndexOf( SLASH ); // 查找最后一个 / 的位置
        if( first == last ) { // 如果第一个/和最后一个/的索引相同，说明uri中只有一个/，即请求路径是 /user
            throw new RuntimeException( "请求路径不符合要求" ); // 这是不合适的
        }
        int index = uri.lastIndexOf( SLASH , last - 1 ) ; // 搜索 last 位置之前 / 最后出现的位置
        if( first == index ) { // 如果倒数第二个/和正数第一个/的索引相同，说明uri中只有两个/，即请求路径是 /user/add
            throw new RuntimeException( "请求路径不符合要求" );
        }
        // 从 uri 中截取 倒数第二个斜杠 和 倒数第一个斜杠 之间的内容
        String operation = uri.substring( index + 1 , last );
        logger.info( operation );

        // 使用 Java 7 中提供的支持: 在 switch 语句中使用了 String 类型
        switch ( operation ) {
            case "add" : add( request , response ); break ;
            case "success" : success( request , response ); break ;
            case "sign-in" : signIn( request , response ); break ;
            case "sign-out" : signOut( request , response ); break ;
            case "edit" : edit( request , response ) ; break ;
            case "setting" : setting( request , response ) ; break ;
            case "change" : change( request , response ) ; break ;
            case "changing" : changing( request , response ) ; break ;
            case "dispose" : dispose( request , response ) ; break ;
            default:
        }

    }

    protected void add( HttpServletRequest request , HttpServletResponse response )
            throws ServletException, IOException {

        request.setCharacterEncoding( "UTF-8" );
        response.setCharacterEncoding( "UTF-8" );

        String username = request.getParameter( "username" );
        String password = request.getParameter( "password" );
        String confirm = request.getParameter( "confirm" );

        HttpSession session = request.getSession();

        final String applicationPath = request.getContextPath() ;
        final String fail = applicationPath + "/user/edit/suibian" ;
        final String success = applicationPath + "/user/sign-in/suibian" ;

        // 数据校(jiao)验
        if( Objects.isNull( username ) || ( username = username.trim() ).isEmpty() ) {
            // 应该返回到 添加页面( edit.html )并显示相应提示
            session.setAttribute( "message" , "你丫没有输入用户名就敢点添加?" );
            response.sendRedirect( fail );
            return ;
        }

        if( Objects.isNull( password ) || ( password = password.trim() ).isEmpty() ) {
            // 应该返回到 添加页面( edit.html )并显示相应提示
            response.sendRedirect( fail );
            return ;
        }

        if( Objects.isNull( confirm ) || ( confirm = confirm.trim() ).isEmpty() ) {
            // 应该返回到 添加页面( edit.html )并显示相应提示
            response.sendRedirect( fail );
            return ;
        }

        if( !password.equals( confirm ) ) { // 注意小括号内部的感叹号
            response.sendRedirect( fail );
            return ;
        }

        User u = new User();
        u.setUsername( username );
        u.setPassword( password );

        // 假设添加的是学生
        u.setUser_role( UserRole.STUDENTS );

        UserService us = new UserService();
        boolean x = us.saveUser( u );

        if( x ) {
            session.setAttribute( "success" , "恭喜你" );
            response.sendRedirect( success );
        } else {
            response.sendRedirect( fail );
        }

    }

    protected void success( HttpServletRequest request , HttpServletResponse response )
            throws ServletException, IOException {
        logger.info( "去往成功页面" );
        String path = "/WEB-INF/success.html" ;
        RequestDispatcher dispatcher = request.getRequestDispatcher( path );
        dispatcher.forward( request , response );
    }

    protected void signIn( HttpServletRequest request , HttpServletResponse response )
            throws ServletException, IOException {
        logger.info( "处理登录请求" );

        final String applicationPath = request.getContextPath() ;
        final String fail = applicationPath + "/sign-in.html" ;
        final String success = applicationPath + "/user/success/suibian" ;

        HttpSession session = request.getSession();

        String username =  request.getParameter( "username" );
        String password =  request.getParameter( "password" );


        // 数据校(jiao)验
        if( Objects.isNull( username ) || ( username = username.trim() ).isEmpty() ) {
            session.setAttribute( "message" , "你丫没有输入用户名就敢点添加?" );
            response.sendRedirect( fail );
            return ;
        }

        if( Objects.isNull( password ) || ( password = password.trim() ).isEmpty() ) {
            session.setAttribute( "message" , "你丫没有输入密码就敢点添加?" );
            response.sendRedirect( fail );
            return ;
        }

        UserService us = new UserService(); // 创建UserService实例
        User user = us.findUser( username ); // 根据用户名返回User实例

        if( Objects.isNull( user ) ) {
            session.setAttribute( "message" , "此用户名在数据库中不存在" );
            response.sendRedirect( fail );
            return ;
        }

        // 对用户输入的密码加盐加密 ( 盐值来自 user 实例 ( 从数据库查询而来 ) )
        String passwd1 = us.encrypt( password , user.getSalt() );
        String passwd2 = user.getPassword() ; // 获取数据库中保存的密码
        // 判断用户在页面上输入的密码是否跟数据库中保存的密码相等
        if( !passwd1.equals( passwd2 ) ) { // 注意感叹号
            session.setAttribute( "message" , "密码错误" );
            session.setAttribute( "username" , username );
            response.sendRedirect( fail );
            return ;
        }

        // 将 User实例 绑定到 会话对象中 ( 非常重要的一步 )
        session.setAttribute( LOGIN_USER , user );
        session.setAttribute( "message" , "登录成功" );
        response.sendRedirect( success );
        logger.info( "登录成功" );
    }

    protected void signOut( HttpServletRequest request , HttpServletResponse response )
            throws ServletException, IOException {
        logger.info( "退出登录" );
        HttpSession session = request.getSession();
        //session.removeAttribute( LOGIN_USER ); // 将User实例从会话对象中移除
        session.invalidate(); // 废弃整个会话
        final String signInPage = request.getContextPath() + "/sign-in.html" ;
        response.sendRedirect( signInPage );
    }

    protected void edit( HttpServletRequest request , HttpServletResponse response )
            throws ServletException, IOException {
        logger.info( "进入个人信息编辑页面" );
        HttpSession session = request.getSession();
        Object o = session.getAttribute( LOGIN_USER );
        if( o instanceof User ) { // o 不是 null 且 o 所指向对象的类型是 User类型
            String path = "/WEB-INF/edit.html";
            RequestDispatcher dispatcher = request.getRequestDispatcher(path);
            dispatcher.forward(request, response);
        } else {
            session.setAttribute( "message" , "请先登录" );
            response.sendRedirect( request.getContextPath() + "/sign-in.html" );
        }
    }

    protected void setting( HttpServletRequest request , HttpServletResponse response )
            throws ServletException, IOException {
        logger.info( "编辑个人信息" );

        final String applicationPath = request.getContextPath() ;

        HttpSession session = request.getSession();
        Object o = session.getAttribute( LOGIN_USER ); // 从会话对象中获取已经登录的用户
        if( o instanceof User ) { // o不为空且o引用的对象是User类型
            User u = (User) o ;

            String nickname = request.getParameter( "nickname" );
            u.setNickname( nickname );

            String name = request.getParameter( "name" );
            u.setName( name );

            String gender = request.getParameter( "gender" );
            u.setGender( gender );

            String dateString = request.getParameter( "birthdate" );
            if( Objects.nonNull( dateString ) ) {
                System.out.println( dateString );
                DateFormat df = new SimpleDateFormat( "yyyy-MM-dd" );
                try {
                    java.util.Date date = df.parse( dateString );
                    Instant instant = date.toInstant();
                    ZoneId zoneId = ZoneId.systemDefault() ;
                    ZonedDateTime zonedDateTime = instant.atZone( zoneId );
                    LocalDate birthdate = zonedDateTime.toLocalDate();
                    u.setBirthdate( birthdate );
                } catch (ParseException e) {
                    e.printStackTrace();
                }
            }

            UserService us = new UserService();
            us.editUser( u );

            final String success = applicationPath + "/user/success/suibian" ;
            response.sendRedirect( success );
        } else {
            session.setAttribute( "message" , "请先登录" );
            response.sendRedirect( applicationPath + "/sign-in.html" );
        }

    }

    protected void change( HttpServletRequest request , HttpServletResponse response )
            throws ServletException, IOException {
        logger.info( "进入个人密码修改页面" );
        HttpSession session = request.getSession();
        Object o = session.getAttribute( LOGIN_USER );
        if( o instanceof User ) { // o 不是 null 且 o 所指向对象的类型是 User类型
            String path = "/WEB-INF/change.html";
            RequestDispatcher dispatcher = request.getRequestDispatcher(path);
            dispatcher.forward(request, response);
        } else {
            session.setAttribute( "message" , "请先登录" );
            response.sendRedirect( request.getContextPath() + "/sign-in.html" );
        }
    }

    protected void changing( HttpServletRequest request , HttpServletResponse response )
            throws ServletException, IOException{
        logger.info("修改个人密码页面");

        final String applicationPath = request.getContextPath() ;

        HttpSession session = request.getSession();
        Object o = session.getAttribute( LOGIN_USER ); // 从会话对象中获取已经登录的用户
        if( o instanceof User ) { // o不为空且o引用的对象是User类型
            User u = (User) o ;

            String password = request.getParameter("password");
            String confirm = request.getParameter("confirm");
            int id = u.getId();

            final String fail = applicationPath + "/user/change/suibian" ;
            final String success = applicationPath + "/user/success/suibian" ;

            if( Objects.isNull( password ) || ( password = password.trim() ).isEmpty() ) {
                // 应该返回到 添加页面( change.html )并显示相应提示
                session.setAttribute("message" ,  "丫的，不能为空");
                response.sendRedirect( fail );
                return ;
            }

            if( Objects.isNull( confirm ) || ( confirm = confirm.trim() ).isEmpty() ) {
                // 应该返回到 添加页面( change.html )并显示相应提示
                session.setAttribute("message" ,  "丫的，不能为空");
                response.sendRedirect( fail );
                return ;
            }

            if( !password.equals( confirm ) ) { // 注意小括号内部的感叹号
                session.setAttribute("message","两次密码不同");
                response.sendRedirect( fail );
                return ;
            }

            u.setPassword(password);
            u.setId(id);

            UserService us = new UserService();
            us.changeUser(u);

            response.sendRedirect( success );
        }else {
            session.setAttribute( "message" , "请先登录" );
            response.sendRedirect( applicationPath + "/sign-in.html" );
        }
    }

    protected void dispose( HttpServletRequest request , HttpServletResponse response )
            throws ServletException, IOException {
        logger.info("注销账户");

        final String applicationPath = request.getContextPath() ;

        HttpSession session = request.getSession();
        Object o = session.getAttribute( LOGIN_USER ); // 从会话对象中获取已经登录的用户
        if( o instanceof User ) { // o不为空且o引用的对象是User类型
            User user = (User) o ;
            UserService us = new UserService();
            us.deleteUser( user );
            response.sendRedirect( applicationPath + "/add.html" );
        } else {
            session.setAttribute( "message" , "请先登录" );
            response.sendRedirect( applicationPath + "/sign-in.html" );
        }
    }

}
